
package com.sq.partner.manager.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.sq.partner.manager.common.Constants;
import com.sq.partner.manager.common.DictCache;
import com.sq.partner.manager.common.exception.AppException;
import com.sq.partner.manager.dao.INlifePlanDao;
import com.sq.partner.manager.mybatis.model.CoinFeeConfig;
import com.sq.partner.manager.mybatis.model.CoinPlanConfig;
import com.sq.partner.manager.mybatis.model.CoreDept;
import com.sq.partner.manager.mybatis.model.DictDto;
import com.sq.partner.manager.mybatis.model.GatewayUser;
import com.sq.partner.manager.mybatis.model.SaleConfig;
import com.sq.partner.manager.service.CoinFeeConfigService;
import com.sq.partner.manager.service.CoinPlanConfigService;
import com.sq.partner.manager.service.ICoreDeptService;
import com.sq.partner.manager.service.IGatewayLifePolicyListService;
import com.sq.partner.manager.service.INlifePlanConfigService;
import com.sq.partner.manager.service.SaleConfigService;
import com.sq.partner.manager.util.ExcelUtil;
import com.sq.partner.manager.util.JsonUtils;
import com.sq.partner.manager.util.LogUtil;
import com.sq.partner.manager.util.Page;
import com.sq.partner.manager.util.SqlUtil;
import com.sq.partner.manager.util.StrUtil;
import com.sq.partner.manager.util.excel.ImportExcelBuilderTool;

/**
 * @date 2017-11-07财险跟单费用配置
 */
@Controller
@RequestMapping("/noCarSaleConfig")
public class NoCarSaleConfigController {
	private static Logger logger = LogUtil.getLog(NoCarSaleConfigController.class);
	@Resource
	private INlifePlanDao nlifePlanDao;
	@Resource
	private INlifePlanConfigService nlifePlanConfigService;
	@Resource
	private SaleConfigService saleConfigService;
	@Resource
	private CoinFeeConfigService coinFeeConfigService;
	
	@Resource
	private CoinPlanConfigService coinPlanConfigService;
	@Resource
	ImportExcelBuilderTool importExcelBuilderTool;
	@Resource
	private IGatewayLifePolicyListService lifePolicyListService;
	@Resource
	private ICoreDeptService iCoreDeptService;
	/**
	 * 跳转方案列表页面
	 */
	@RequestMapping(value = "/index")
	public String list() throws Exception {
		logger.info("执行跳转到跟单费用配置列表界面");
		return "noCarProduct/noCarSale/index";
	}
	/**新增跟单费用配置打开div*/
	@RequestMapping(value = "/addFeeConfigDiv")
	@ResponseBody
	public Map<String, Object> addFeeConfigDiv() throws Exception{
		Map<String, Object> map=new HashMap<String, Object>();
		try {
			/**查询配置维度列表*/
			List<DictDto> weidTypes=DictCache.getDict(Constants.DICT_NOCAR_WEID_TYPE);
			/***查询最大跟单配置代码**/
			String agentNo=saleConfigService.queryNextAgentNo("NoCarFYGD");
			map.put("weidTypes", weidTypes);
			map.put("agentNo", agentNo);	
		} catch (Exception e) {
			logger.error("查询数据库错误"+e);
		}
		return map;
	}
	/**保存三费信息*/
	@RequestMapping(value = "/saveCoinFee")
	@ResponseBody
	public Map<String, Object> saveCoinFee(HttpSession session,String coinFee,String agentNo,String copyOrUpdate,String copyaddName) throws Exception{
		Map<String, Object> map=new HashMap<String, Object>();
		if(StrUtil.isEmpty(agentNo)){
			map.put("success", false);
			map.put("message", "参数异常");
			return map;
		}
		GatewayUser user = (GatewayUser)session.getAttribute(Constants.SESSION_USER);
		String title="";
		try {
			/**判断操作类型**/
			if("copy".equals(copyOrUpdate)){
			   SaleConfig saleConfig=saleConfigService.searchSaleConfigById(agentNo);
			   saleConfig.setAgentName(copyaddName);
			   saleConfig.setInsertDate(new Date());
			   saleConfig.setOperatorCode(user.getUserCode());
				/***查询最大跟单配置代码**/
			   agentNo=saleConfigService.queryNextAgentNo("NoCarFYGD");
			   saleConfig.setAgentNo(agentNo);
			   saleConfigService.addSaleConfig(saleConfig);
			   title=",跟单费用代码"+agentNo;
			}else{
				/**更新配置名称**/
				SaleConfig sale=new SaleConfig();
				sale.setAgentNo(agentNo);
				sale.setAgentName(copyaddName);
				saleConfigService.updateSaleConfig(sale);
			}
			if(coinFeeConfigService.addCoinFee(agentNo,strToJson(coinFee, agentNo))){
				map.put("success", true);
				map.put("message", "添加成功"+title);
			}else{
				map.put("success", false);
				map.put("message", "操作失败，请重试");
			};
		} catch (Exception e) {
			logger.error("查询数据库错误"+e);
			map.put("success", false);
			map.put("message", "操作失败，请重试");
		}
		return map;
	}
	/**将String类型转换成json*/
	private List<CoinFeeConfig> strToJson(String coinFee,String agentNo){
		List<CoinFeeConfig> coins=new ArrayList<CoinFeeConfig>();
		List<Map<String,String>> list = JsonUtils.parseJson(coinFee, ArrayList.class);
		if(list!=null){
			for (Map<String, String> map : list) {
				CoinFeeConfig coin=new CoinFeeConfig();
				coin.setAgentNo(agentNo);
				coin.setBranch(map.get("branch"));
				coin.setBusinessRate(Double.parseDouble(map.get("businessRate"))/100);
				coin.setCommRate(Double.parseDouble(map.get("commRate"))/100);
				coin.setMarketRate(Double.parseDouble(map.get("marketRate"))/100);
				coin.setChannelSource(map.get("channelSource"));
				coin.setSysSource(map.get("sysSource"));
				coin.setProductType(map.get("prototype"));
				coin.setEmpNo(map.get("empNo"));
				coin.setSeq(Integer.parseInt(map.get("seq")));
				coin.setPriority(map.get("sumProp"));
				coin.setOprateTime(new Date());
				coins.add(coin);
			}
		}
		return coins;
	}
	/**新增跟单费用配置保存*/
	@RequestMapping(value = "/saveFeeConfig")
	@ResponseBody
	public Map<String, Object> saveFeeConfig(SaleConfig saleConfig,HttpServletRequest request) throws Exception{
		Map<String, Object> map=new HashMap<String, Object>();
		HttpSession session = request.getSession(); 
		GatewayUser user = (GatewayUser)session.getAttribute(Constants.SESSION_USER);
		saleConfig.setInsertDate(new Date());
		/**新意见险0 财险1*/
		saleConfig.setAgentType("1");
		saleConfig.setOperatorCode(user.getUserCode());
		logger.info("操作用户"+user.getUserCode());
		try {
			boolean flag=saleConfigService.addSaleConfig(saleConfig);
			if(!flag){
				map.put("message", "保存失败");
			}else{
				map.put("message", "保存成功");	
			}
			map.put("success", flag);
		} catch (Exception e) {
			logger.error("保存跟单费用配置错误",e);
			map.put("success", false);
			map.put("message", "保存跟单费用配置错误");
		}
		return map;
	}
	/**删除跟单费用配置*/
	@RequestMapping(value = "/deleteSaleConfig")
	@ResponseBody
	public Map<String, Object> deleteSaleConfig(SaleConfig saleConfig,HttpServletRequest request) throws Exception{
		Map<String, Object> map=new HashMap<String, Object>();
		logger.info("执行删除跟单费用"+saleConfig.getAgentNo());
		try {
			//判断是否已关联方案
			Integer count=coinPlanConfigService.queryCoinFeeCount(saleConfig.getAgentNo());
			String planNos=coinPlanConfigService.queryCoinFeeList(saleConfig.getAgentNo());
			if(count>0){
				map.put("message", "该条费用配置信息已与出单方案"+planNos+"进行关联，不允许删除");
				map.put("success", false);
				return map;
			}
			boolean flag=saleConfigService.delSaleConfig(saleConfig);
			/**删除三费信息*/
			coinFeeConfigService.deleteCoinFee(saleConfig.getAgentNo());
			if(!flag){
				map.put("message", "删除失败");
			}else{
				map.put("message", "删除成功");	
			}
			map.put("success", flag);
		} catch (Exception e) {
			logger.error("保存跟单费用配置错误",e);
			map.put("success", false);
			map.put("message", "删除跟单费用配置错误");
		}
		return map;
	}
	/**查询列表*/
	@RequestMapping(value = "/querySalePageByCriteria")
	@ResponseBody
	public Page<Map<String,Object>> querySalePageByCriteria(HttpSession session,Page<Map<String,Object>> page,SaleConfig saleConfig) throws Exception{
		Map<String,Object> paramMap = SqlUtil.buildPageMap(page);
		paramMap.put("agentType", "1");
		paramMap.put("agentNo", ("").equals(saleConfig.getAgentNo())?null:saleConfig.getAgentNo());
		paramMap.put("agentName", ("").equals(saleConfig.getAgentName())?null:saleConfig.getAgentName());
		paramMap.put("bigdate", ("").equals(saleConfig.getBigdate())?null:saleConfig.getBigdate());
		paramMap.put("smallDate", ("").equals(saleConfig.getSmallDate())?null:saleConfig.getSmallDate());
		/**查询配置维度列表*/
		List<DictDto> weidTypes=DictCache.getDict(Constants.DICT_NOCAR_WEID_TYPE);
		paramMap.put("weids", weidTypes);
		page.setMap(paramMap);
		page = saleConfigService.queryPageByCriteria(page);
		return page;
	}
	/***
	 * 查询三费列表
	 */
	@RequestMapping(value = "/queryCoins")
	@ResponseBody
	public Map<String, Object> queryCoins(SaleConfig saleConfig,HttpServletRequest request) throws Exception{
		Map<String, Object> map=new HashMap<String, Object>();
		try {
			String seq=coinFeeConfigService.queryMaxSeq(saleConfig.getAgentNo());
			map.put("agentNo", Integer.parseInt(seq));
			List<CoinFeeConfig> coins=coinFeeConfigService.queryCoins(saleConfig.getAgentNo());
			map.put("coins", coins);
		} catch (Exception e) {
			logger.error("数据库操作错误",e);
			map.put("success", false);
			map.put("message", "数据库操作错误");
		}
		return map;
	}
	/**
	 * 加载接口传入方案三费列表
	 * @param page
	 * @param planNo
	 * @param agentType
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/queryAgentInfoRelaPageByCriteria")
	@ResponseBody
	public Page<Map<String,Object>> queryAgentInfoRelaPageByCriteria(Page<Map<String,Object>> page,
							  		String planNo,String agentType) throws Exception{
		if(StrUtil.isEmpty(planNo)){
			page.setResult("planNo不能为空");
			return page;
		}
		Map<String,Object> paramMap = SqlUtil.buildPageMap(page);
		paramMap.put("planNo", planNo);
		
		page.setMap(paramMap);
		page = nlifePlanConfigService.queryAgentInfoRelaPageByCriteria(page,agentType);
		
		return page;
	}
	
	/***
	 * 跟单费用 维度下拉框
	 */
	@RequestMapping(value = "/querySelectOption")
	@ResponseBody
	public Map<String, Object> querySelectOption(HttpSession session) throws Exception{
		Map<String, Object> map=new HashMap<String, Object>();
		try {
			GatewayUser user=(GatewayUser) session.getAttribute(Constants.SESSION_USER);
			logger.info("当前登录用户的userCode为"+user.getUserCode()+",DepartmentStr:"+user.getDepartmentStr());
			if(null != user && StrUtil.isNotEmpty(user.getDepartmentStr())){
				List<CoreDept> depts=lifePolicyListService.queryPrivilegeBranch(user.getDepartmentStr());
				map.put("depts", depts);
			}
			List<DictDto> channelSouce=DictCache.getDict(Constants.DICT_SALE_CHANNEL_SOURCE);
			List<DictDto> prodTypes=DictCache.getDict(Constants.DICT_NOCAR_PRODUCT_TYPE);
			map.put("channelSouce", channelSouce);
			map.put("prodTypes", prodTypes);
		} catch (Exception e) {
			logger.error("数据库操作错误",e);
			map.put("success", false);
			map.put("message", "数据库操作错误");
		}
		return map;
	}
	/**
	 * 导入跟单费用配置
	 * @param reconciliationFile
	 * @param response
	 * @param session
	 * @param calDefId
	 * @param tradProdCode
	 * @throws Exception
	 */
	@RequestMapping(value = "/calTemplateImport")
	public void calTemplateImport(@RequestParam MultipartFile myfiles,HttpServletResponse response, HttpSession session,String calDefId,String prodCode,String weid) throws Exception {
		response.setContentType("text/html");
		response.setCharacterEncoding("UTF-8");
		Map<String,Object> map=new HashMap<String, Object>();
		PrintWriter out = null;
		try {
			InputStream inputStream=getFileInputStream(myfiles);
			out = response.getWriter();
			if(inputStream!=null&&StrUtil.isNotEmpty(weid)){
				map.put("coins", getCoinFees(inputStream, weid));
			}
			map.put("success", true);
		} catch (Exception e) {
			map.put("success", false);
			map.put("massage", e.getMessage());
			logger.info("批量导入",e);
		}
		out.write(JsonUtils.toJson(map));
	}
	/***
	 * 获取数据流
	 */

	public InputStream getFileInputStream(MultipartFile  myfiles) throws AppException {
		InputStream inputStream =null;
		try {
			String fileNameStr = myfiles.getOriginalFilename();
			int lastDotIndex = fileNameStr.lastIndexOf(".");
			if(-1==lastDotIndex){
				throw new AppException("请选择扩展名为 .xls 的文件上传");
			}else{
				String extName = fileNameStr.substring(lastDotIndex+1,fileNameStr.length());
				if(!"xls".equals(extName.toLowerCase())){
					throw new AppException("请选择扩展名为 .xls 的文件上传");
				}
			}
			if (myfiles.isEmpty()) {
				throw new AppException("上传失败，上传文件不能为空！");
			} else {
				inputStream = myfiles.getInputStream();
			}
		} catch (IOException e) {
			logger.info("上传错误!请稍后重试",e);
			throw new AppException("上传错误!请稍后重试");
		}
		return inputStream;
	}
	/**获取数据
	 * @throws IOException */
	private List<CoinFeeConfig> getCoinFees(InputStream inputStream,String weid) throws Exception{
		HSSFWorkbook workBook = new HSSFWorkbook(inputStream);
		HSSFSheet sheet=workBook.getSheetAt(0);
		int lastRowNumber = sheet.getLastRowNum();
		List<CoinFeeConfig> coins=new ArrayList<CoinFeeConfig>();
		StringBuffer errMessage=new StringBuffer("导入失败：<br>");
		int errCount=0;
		if(lastRowNumber<2){
			errMessage.append("模板数据为空  <br>");
			errCount++;
		}
		Map<String, Boolean> map=new HashMap<String, Boolean>();
		List<String> branchName=new ArrayList<String>();
		for (int rowNum = 2; rowNum <= sheet.getLastRowNum(); rowNum++) {
			HSSFRow hssfRow = sheet.getRow(rowNum);
			CoinFeeConfig  coinFeeConfig=new CoinFeeConfig();
			/**判断当前配置的维度*/
			String[] strs=weid.split(",");
			String weidflag=",";
			for (int i = 0; i < strs.length; i++) {
				String weidValue= ExcelUtil.getCellText(hssfRow.getCell(Integer.parseInt(strs[i]))).trim();
				weidflag+=weidValue+",";
			}
			if(errCount>=10){
				throw  new AppException(errMessage.toString());
			}
			if(map.get(weidflag)!=null&&map.get(weidflag)){
				errMessage.append("第"+(rowNum+1)+"行，维度信息存在重复，相同维度信息只能有一个<br>");
				errCount++;
				continue;
			}else{
				map.put(weidflag, true);
			}
			//三费校验
			Double totalFee=0.0;
			String regex = "^[0-9]+(.[0-9]+)?$";  
			if(StrUtil.isEmpty( ExcelUtil.getCellText(hssfRow.getCell(5)).trim())){
				errMessage.append("第"+(rowNum+1)+"行，手续费比例为空<br>");
				errCount++;
				continue;
			}else{
				if(!ExcelUtil.getCellText(hssfRow.getCell(5)).trim().matches(regex)){
					errMessage.append("第"+(rowNum+1)+"行，手续费比例只能输入数字小数点<br>");
					errCount++;
					continue;
				}
				totalFee=totalFee+Double.parseDouble(ExcelUtil.getCellText(hssfRow.getCell(5)).trim());
			}
			if(StrUtil.isEmpty(ExcelUtil.getCellText(hssfRow.getCell(6)).trim())){
				errMessage.append("第"+(rowNum+1)+"行，市场维护费比例为空<br>");
				errCount++;
				continue;
			}else{
				if(!ExcelUtil.getCellText(hssfRow.getCell(6)).trim().matches(regex)){
					errMessage.append("第"+(rowNum+1)+"行，市场维护费比例只能输入数字小数点<br>");
					errCount++;
					continue;
				}
				totalFee=totalFee+Double.parseDouble(ExcelUtil.getCellText(hssfRow.getCell(6)).trim());
			}
			if(StrUtil.isEmpty( ExcelUtil.getCellText(hssfRow.getCell(7)).trim())){
				errMessage.append("第"+(rowNum+1)+"行，业务绩效比例为空<br>");
				errCount++;
				continue;
			}else{
				if(!ExcelUtil.getCellText(hssfRow.getCell(7)).trim().matches(regex)){
					errMessage.append("第"+(rowNum+1)+"行，业务绩效比例只能输入数字小数点<br>");
					errCount++;
					continue;
				}
				totalFee=totalFee+Double.parseDouble(ExcelUtil.getCellText(hssfRow.getCell(7)).trim());
			}
			if(totalFee>=100){
				errMessage.append("第"+(rowNum+1)+"行，三费之和必须小于100%<br>");
				errCount++;
				continue;
			}
			if(errCount>=10){
				throw  new Exception(errMessage.toString());
			}
			for (int i = 0; i < strs.length; i++) {
				String weidValue= ExcelUtil.getCellText(hssfRow.getCell(Integer.parseInt(strs[i]))).trim();
				/**机构*/
				if(Integer.parseInt(strs[i])==0){
					coinFeeConfig.setBranch(weidValue);	
					branchName.add(weidValue);
				}
				/**业务来源*/
				if(Integer.parseInt(strs[i])==1){
					coinFeeConfig.setChannelSource(weidValue);	
				}
				/**产品大类 */
				if(Integer.parseInt(strs[i])==2){
					coinFeeConfig.setProductType(weidValue);	
				}
				/**代理人业务员 */
				if(Integer.parseInt(strs[i])==3){
					coinFeeConfig.setEmpNo(weidValue);	
				}
				/**系统来源 */
				if(Integer.parseInt(strs[i])==4){
					coinFeeConfig.setSysSource(weidValue);	
				}
			}
			coinFeeConfig.setCommRate(Double.parseDouble(ExcelUtil.getCellText(hssfRow.getCell(5)).trim()));
			coinFeeConfig.setMarketRate(Double.parseDouble(ExcelUtil.getCellText(hssfRow.getCell(6)).trim()));
			coinFeeConfig.setBusinessRate(Double.parseDouble(ExcelUtil.getCellText(hssfRow.getCell(7)).trim()));
			coins.add(coinFeeConfig);
		}
		/**机构中英文转换**/
		if(branchName!=null&&branchName.size()>0){
			Map<String, String> branchMap=iCoreDeptService.queryDeptNameList(branchName);
			for (int i = 0; i < coins.size(); i++) {
				if(errCount>=10){
					throw  new AppException(errMessage.toString());
				}
				String branch=branchMap.get(coins.get(i).getBranch());
				if(StrUtil.isEmpty(branch)){
					errMessage.append("机构号为"+coins.get(i).getBranch()+"有误请检查<br>");
					errCount++;
					continue;
				}else{
					coins.get(i).setBranchName(branch);
				}
				
			}
		}
		if(errCount>0){
			throw  new AppException(errMessage.toString());
		}
		return coins;
	}

	/**
	 * 费用跟单配置模板下载
	 */
	@RequestMapping(value = "/downloadUserTemplet", method = RequestMethod.GET)
	public void downloadUserTemplet(HttpServletResponse response,HttpServletRequest request ,String templateType) throws IOException{
		String root = Thread.currentThread().getContextClassLoader().getResource("").getPath();
		 String path = root.substring(0, root.indexOf("WEB-INF"))+"template"+File.separator+"nocarsale"+File.separator+"nocarsaletemplate.xls";

		// 以流的形式下载文件
		InputStream inputStream=null;
		OutputStream outputStream =null;
		try {
			File file = new File(path);
			// 取得文件名。
			String filename = file.getName();
			inputStream = new BufferedInputStream(new FileInputStream(path));
			byte[] buffer = new byte[inputStream.available()];
			inputStream.read(buffer);
			//清空response
			response.reset();
			//设置response的Header
			response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
			response.addHeader("Content-Length", "" + file.length());
			outputStream = new BufferedOutputStream(response.getOutputStream());
			response.setContentType("application/octet-stream");
			outputStream.write(buffer);
			outputStream.flush();
		}catch (Exception e) {
			logger.info(e);
		}finally{
			if(null!=inputStream){
				inputStream.close();
			}
			if(null!=outputStream){
				outputStream.close();
			}
		}
	}
}
